import axios from 'axios';
import querystring from 'querystring';
import url from 'url'
import MD5 from 'crypto-js/md5';
import UcUtils from '../ucUtils';
import UcConfig from '../ucConfig';
import UcRequest, { UcResponse } from './ucRequest';
/**
 * @constant {string} 客户端版本号
 */
const UC_CLIENT_RELEASE = '20170101'

export default class UcClient
{
    /**
     * 
     * @param {UcConfig} config 
     */
    constructor(config){
        this.ucApi = config.ucApi
        this.ucIp = config.ucIp
        this.ucAppId = config.ucAppId
        this.ucKey = config.ucKey
        this.httpUserAgent = config.httpUserAgent
    }

    /**
     * 
     * @param {UcRequest} req
     * @returns {Promise<object>}
     */
    request(req){
        let ip = this.ucIp, api = this.ucApi;
        if(ip.length > 0){ 
            // 如果设置了ip，优先使用ip。
            // 例如：ucApi为“http://bbs.local/uc_server”,ucIp为“127.0.0.1”，此时ucApi将变为“http://127.0.0.1/uc_server”
            let urlParts = url.parse(api)
            urlParts.host = ip
            api = url.format(urlParts)
        }
        let reqData = this._buildRequestData(req)
        let reqConf = {
            url:'index.php', // 网络请求最终的目标地址为 ：“服务端地址”+“index.php”，如：“http://127.0.0.1/uc_server/index.php”
            baseURL:api, // 服务端地址，如：“http://127.0.0.1/uc_server”
            timeout: 15 * 1000, // 默认超时时间设置为15秒即可
            headers:{
                'user-agent':this.httpUserAgent, // 请求头部的user_agent必须和请求正文input字段中的agent保持一致
                'content-type':'application/x-www-form-urlencoded', // ucServer端无法处理json格式
            }
        };
        if(req.httpMethod === 'get'){
            reqConf.method = 'get'
            reqConf.params = querystring.parse(reqData) // get请求时，请求的参数放在query string部分
        }else{
            reqConf.method = 'post'
            reqConf.data = reqData // post请求时，请求的参数放在body部分
        }
        return axios.request(reqConf).then(resp=>{
            if(resp.status === 200){
                return resp.data
            }
            // 其他的http响应状态时直接抛异常            
            throw new UcClientError(resp.statusText,resp);
        });
    }

    /**
     * 构造请求数据
     * 
     * 该方法生成的数据将被直接用在post操作的body或者get操作的query string部分
     * @param {UcRequest} req 
     */
    _buildRequestData(req){
        let arg = querystring.stringify(req.params),
            agent = MD5(this.httpUserAgent).toString(),
            now = parseInt((new Date).getTime() / 1000), // 时间戳单位为秒
            inputRaw = `${arg}&agent=${agent}&time=${now}`; // 请求参数中追加agent、当前时间戳信息，其中agent信息在uc server端是会参与校验
        let encoder = UcUtils.getUcEncoder(this.ucKey),
            inputEncoded = encodeURIComponent(encoder.encode(inputRaw)); // 加密后的内容需要执行url encode操作
        return `m=${req.module}&a=${req.action}&inajax=${2}&release=${UC_CLIENT_RELEASE}&input=${inputEncoded}&appid=${this.ucAppId}`;
    }
}


export class UcClientError extends Error
{
    constructor(message, extra) {
        super(message)
        this.name = 'UcClientError';
        this.message = message || '请求错误';
        this.extra = extra;
        this.stack = (new Error).stack
    }
}